from flask import Flask

from flask_socketio import SocketIO,emit
import time

app = Flask(__name__)

socketio = SocketIO()

socketio.init_app(app)


"""

对app进行一些路由设置

"""

"""

对socketio进行一些监听设置

"""

if __name__ == '__main__':

    socketio.run(app,debug=True,host='0.0.0.0',port=5000)

#这里就不再用app.run而用socketio.run了。socketio.run的参数和app.run也都差不多
# 上面的，对app的路由设置就不再说了，想说的是对socketio的监听设置，这才是真正关系到前后端websocket通信过程的。
# 结合前面的前端代码，socketio的监听设置可以这样做
@socketio.on('request_for_response',namespace='/testnamespace')

def give_response(data):

    value = data.get('param')

#进行一些对value的处理或者其他操作,在此期间可以随时会调用emit方法向前台发送消息

    emit('response',{'code':'200','msg':'start to process...'})

    time.sleep(5)

    emit('response',{'code':'200','msg':'processed'})

# socketio也用了和app.route类似的装饰器的形式进行监听设置。主要参数中有namespace这一项，也就是这项指定了这个监听的范围。在前端，只有注册在testnamespace上的socket，emit向request_for_response的消息才会被这个函数接受并处理。处理函数自带一个参数用来接收前端emit来消息中的那个object，在处理函数中可以对其解析处理。随后后端向前端发送了start to process的消息。也使用了emit这个方法，然后指明了监听是response。也就是说前端on在response上的监听处理函数会处理这个消息(当然还是在testnamespace的框架内)。发出消息后后端不会被阻塞而是继续向下执行，在处理了5秒钟之后发出了结束处理的消息，前端自然隔了五秒之后就得到了这个消息了。

# socket监听响应函数本身不需要返回什么值，只需要在处理过程中适当的位置emit出消息即可。

# 网上其他一些教程中会提到send方法来取代emit方法的位置(无论是前端还是后端)，其实send方法就是把上文中的'request_for_response','response'这两个标识都默认成'message'。如此在写的时候就不用写事件名，直接写要传递的参数即可。反过来看，用emit方法实际上是做了一个自定义事件的工作，可以说更加灵活多变一点。

# 略大项目中Manager的支持

# 一般而言，上面那样的socketio.run总给人感觉是个玩具项目。如果要做一个大型的项目那肯定得用一些更加高端的启动方式才行，另外配置也应该有独立的config.py，通过app.config.form_object的方法来填充配置。

# 但是经过我的实验，虽然用manager.run可以让socketio工作，但是似乎会存在类似于缓存一样的一种机制。也就是说后台emit出来的信息并不直接发送到前端，而是在整个响应函数执行结束之后一股脑儿的爆出来。不知道是后端发送时进行了缓存还是前端接收时进行了缓存。

# 所以如果要用websocket的话尽量还是用socketio.run这种方法启动把。至于配置可以在socketio.run中添加类似于debug=current_app.config['DEBUG'],host=current_app.config['HOST']这样的方法。